package com.swan.security.interceptor;

import com.swan.security.auto.config.SecurityConfig;
import com.swan.web.auto.config.SpringWebConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import java.util.Collection;
import java.util.function.Supplier;

/** 接口权限校验拦截器
 * @author zongf
 * @date 2025-02-19
 */
@Slf4j
@Component
public class AuthPermissionInterceptor implements AuthorizationManager<RequestAuthorizationContext> {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Autowired
    private SecurityConfig securityConfig;

    @Autowired
    private SpringWebConfig springWebConfig;

    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication, RequestAuthorizationContext context) {

        // 如果未开启 API 校验，则直接返回
        if (!securityConfig.isCheckApiPermission()) {
            return new AuthorizationDecision(true);
        }

        // 获取请求路径地址，移除统一接口前缀
        String requestUri = context.getRequest().getRequestURI().substring(springWebConfig.getServerContextPath().length());

        // 获取用户接口权限列表
        Collection<? extends GrantedAuthority> authorities = authentication.get().getAuthorities();

        // 校验接口权限
        boolean hasAuth =  authorities.stream().anyMatch(authUrl ->   antPathMatcher.match(authUrl.getAuthority(), requestUri) );

        log.info("[校验用户权限] url:{}, result:{}", requestUri, hasAuth);

        // 该方法不需要抛出异常，当返回为 false 时, 上游会捕获异常，然后写入 response 中，httpCode 为403。
        return new AuthorizationDecision(hasAuth);
    }
}
